﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once
#include "GnufBase.h"
#include "GnufUiCommonDef.h"
#include "GnufBaseUtils.h"

namespace gnuf {
    class Color;
    class ColorBoard final
    {
        friend class ColorPalette;
    public:
        ColorBoard(ETheme theme) : m_theme(theme), m_disabledAlphaValue(255){}
        ~ColorBoard() {}
        
        // add a color number into current color board.
        void addColor(const std::wstring& key, const std::wstring& value, int disabledAlpha)
        {
            ColorCode code = BaseUtil::toColorCode(key);
            DBG_WARN_AND_RETURN_VOID_UNLESS(code != ColorCode::Invalid, L"invalid color key", L"GMEP", L"2021-02-25");

            m_codeToColorMap[code] = parseColorByValue(value);
            m_codeToDisableColorMap[code] = parseColorByValue(value).setAlpha(disabledAlpha);
        }

        void setDisabledAlphaValue(int value) { m_disabledAlphaValue = value; }
        int getDisabledAlphaValue() const { return m_disabledAlphaValue; }

        // get the theme of this board.
        ETheme theme() const {return m_theme; }
    private:

        // check out the real hex color corresponding to the given color number.
        // the only client of this method should be a color palette.
        const Color& getColorByCode(ColorCode code) const
        {
            if (m_codeToColorMap.find(code) == m_codeToColorMap.end())
                return m_codeToColorMap.begin()->second;

            return m_codeToColorMap.at(code);
        }

        const Color& getDisabledColorByCode(ColorCode code) const
        {
            if (m_codeToDisableColorMap.find(code) == m_codeToDisableColorMap.end()) 
                return m_codeToDisableColorMap.begin()->second;

            return m_codeToDisableColorMap.at(code);
        }

        Color parseColorByValue(const std::wstring& value) const;

        std::map<ColorCode, Color> m_codeToColorMap;
        std::map<ColorCode, Color> m_codeToDisableColorMap;
        int m_disabledAlphaValue;

        ETheme m_theme;
    };

    class ColorPalette final
    {
    public:
        ColorPalette();
        ~ColorPalette();

        // initialize the color palette via ColorPalette.xml.
        void initialize();

        // add an color board into the system.
        ColorBoard* addColorBoard(ETheme theme);

        // get a Color instance via given color code that compatible to the current theme.
        const Color& colorBy(ColorCode code, bool disabled = false) const;

        // change the theme of the color palette.
        void setTheme(ETheme theme);
        ETheme theme() const { return m_currBoard->theme(); }
    private:
        // check out the color board of the corresponding theme.
        const ColorBoard* getColorBoard(ETheme theme) const;

        // the color board set should be shared with all palette instances.
        static std::list<gcmp::OwnerPtr<ColorBoard>> s_colorBoards;
        const ColorBoard* m_currBoard;
    };
}
